package graphicView;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import model.FileHandler;
import model.Puzzle;

/**
 * GraphicUI is the swing implementation of the user interface.
 * It manages the menu, puzzle picture, text fields, and button.
 * It listens for various events.
 * @author David Hutchens - modified from Beth Katz's SWT code  
 */

public class GraphicUI extends JPanel
		implements MouseListener, ActionListener {
	
	private static final long serialVersionUID = 1L;
	private JFrame frame;
	private GraphicController controller;
	private JTextField inputField;
	private JTextArea theOutputMessage;
	private JScrollPane JSP;
	private Container Panel;
	private LayoutManager Layout;
	
	private static int LetterSize = 20;
	private static int borderSize = 15;
	private static int MaxDrawingWidth = 10000;
	private static int MinDrawingWidth = 300;
	
	private static final String saveMenuText = "Save UML";
	private static final String openMenuText = "Open UML";
	private static final String insertText = "Insert";
	private static final String relationshipText = "Relationship";
	private static final String classText = "Class";
	private static final String packageText = "Package";
	private static final String putText = "Put";
	private static final String findButtonText = "Find Word";
	
	
	/**
	 * Constructor for GraphicUI uses the single Display object
	 * which has a single Shell (window) inside (it could have more),
	 * and puts some things inside the shell
	 */
	public GraphicUI(GraphicController aController, JFrame aFrame) {
		frame = aFrame;
		controller = aController;
	   	JPanel widgetPanel = setupLayout();
	   	frame.getContentPane().add(widgetPanel, BorderLayout.CENTER);
		createMenu(frame);
		createTextItems(widgetPanel);
		createButton(widgetPanel);
		setSizes();
		addMouseListener(this);
	}
	
	/**
	 * returns the current puzzle
	 * @return the current puzzle
	 */
	public Puzzle puzzle() {
		return controller.puzzle();
	}
	
	/**
	 * Sets the sizes based on the current puzzle.
	 */
	public void setSizes() {
/*		Puzzle thePuzzle = puzzle();
		Dimension puzzleDrawingSize = new Dimension (thePuzzle.numberOfColumns()*LetterSize + borderSize*2,
													 thePuzzle.numberOfRows()*LetterSize + borderSize*2);
		setMinimumSize(puzzleDrawingSize);
	   	setPreferredSize(puzzleDrawingSize);
	   	setMaximumSize(puzzleDrawingSize);
	   	revalidate();*/
	}
	
	/**
	 * Paints a graphical version of the puzzle.
	 */
	public void printPuzzle( ) {
		repaint();
	}
	
	/**
	 * Draws the painted portions when requested.
	 * @param Graphics gc the graphics context in which to draw 
	 */
	public void paintComponent(Graphics gc) { 
		Puzzle thePuzzle = puzzle();
		if (isOpaque()) { //paint background
            gc.setColor(getBackground());
            gc.fillRect(0, 0, getWidth(), getHeight());
		}
		gc.setColor(new Color(87, 63, 207)); 	
		gc.setFont(new Font("Times", Font.BOLD, 18));
		gc.translate(0,10);
		
		int theRows = thePuzzle.numberOfRows( );
		int theCols = thePuzzle.numberOfColumns( );
		for (int i = 1; i <= theRows; i++) {
			for (int j = 1; j <= theCols; j++) {
				String s = String.valueOf(thePuzzle.charAt(i,j));
				gc.drawString(s, LetterSize*j, LetterSize*i);
			}
		}
		
		gc.translate(0,-10);
	} 
	
	/**
	 * Set up the layout for the interface
	 * @return returns the JPanel that will hold the widgets and this UI
	 */
	private JPanel setupLayout() {
		
	    AdjustmentListener adjustmentListener = new AdjustmentListener() {
	        public void adjustmentValueChanged(AdjustmentEvent adjustmentEvent) {
	          System.out.println("Adjusted: " + adjustmentEvent.getValue());
	        }
	      };		
		
	     JLabel label  = new JLabel(); 
	      
	     
	    Layout = new BorderLayout();
	    setLayout(new BorderLayout());
		JPanel widgetPanel = new JPanel();
		
		JScrollPane JSP = new JScrollPane(widgetPanel);
		
		
//		Panel = getContentPane();
		
		JFrame JFK = new JFrame();
		JFK.setContentPane(new JScrollPane());
		JFK.getContentPane().add(widgetPanel);
		//JFK.getContentPane().add(JSP, BorderLayout.CENTER);
        JFK.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JFK.setSize(400,400);
        JFK.setVisible(true);     
        
       
        
		JScrollBar JSBH = new JScrollBar(JScrollBar.HORIZONTAL, 10, 10, 0, 500);
		//JSBH.setMaximum(500);
		JSBH.addAdjustmentListener(adjustmentListener);
		
		  JSBH.setUnitIncrement(2);
	      JSBH.setBlockIncrement(1);
		
		
		JScrollBar JSBV = new JScrollBar(JScrollBar.VERTICAL, 10, 10, 0, 500);
		//JSBV.setMaximum(400);
		JSBV.addAdjustmentListener(adjustmentListener);
		
		JSBH.setOrientation(JScrollBar.HORIZONTAL);
		
		widgetPanel.setPreferredSize(new Dimension(400, 400));
		widgetPanel.setBorder(BorderFactory.createLineBorder(Color.blue,  2));
		
		widgetPanel.add(JSBH, "North");
		
		JFK.add(JSP);
		
		
		
	/*	JFrame JFK = new JFrame();
		JFK.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    JFK.add(JSBH, BorderLayout.NORTH);
	    JFK.setSize(300, 200);
	    JFK.setVisible(true);*/
	    
		
	/*	widgetPanel.add(JSBH, BorderLayout.SOUTH);
		widgetPanel.add(JSBV, BorderLayout.EAST);*/
				
		
 /* 
		widgetPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
		widgetPanel.setLayout(new BoxLayout(widgetPanel, BoxLayout.PAGE_AXIS));
		widgetPanel.add(this);
	   	
	   	Dimension puzzleDrawingSize = new Dimension(LetterSize, LetterSize);
	   	setMinimumSize(puzzleDrawingSize);
	   	setPreferredSize(puzzleDrawingSize);
	   	setMaximumSize(puzzleDrawingSize);
	   	setBorder(BorderFactory.createLineBorder(Color.lightGray, 2));*/
	  
	   	return widgetPanel;
	}
	
	/**
	 * Creates all parts of the menu for the application.
	 * @param frame the enclosing frame for the interface
	 */
	private void createMenu(JFrame frame) {
			
		//The Black State
		JMenuItem subMenuItem;
		JMenu	Insert;
		
		// create a menu bar
		JMenuBar menuBar = new JMenuBar();
		frame.setJMenuBar(menuBar);
				
		// create the File Item on the menu bar
		JMenu fileMenu = new JMenu("File"); 
		menuBar.add(fileMenu);
	
		
		// create the openPuzzle submenu item and listen for it
		JMenuItem openPuzzle = new JMenuItem(openMenuText); 
		openPuzzle.addActionListener(this);
		fileMenu.add(openPuzzle);
		
		// create the savePuzzle submenu item and listen for it
		JMenuItem savePuzzle = new JMenuItem(saveMenuText); 
		savePuzzle.addActionListener(this);
		fileMenu.add(savePuzzle);
		
		// create the Edit Item on the menu bar
		JMenu editMenu = new JMenu("Edit"); 
		menuBar.add(editMenu);
		
/*		JMenuItem Insert = new JMenuItem(insertText); 
		Insert.addActionListener(this);
		editMenu.add(Insert);*/
		
		
		JMenuItem Package = new JMenuItem(packageText); 
		Package.addActionListener(this);
		
		JMenuItem Class = new JMenuItem(classText);
		Class.addActionListener(this);
		
		JMenuItem Relationship = new JMenuItem(relationshipText);
		Relationship.addActionListener(this);
		
			
		Insert = new JMenu("Insert");
		Insert.setMnemonic(KeyEvent.VK_S);
		subMenuItem = new JMenuItem("Package");
		/*subMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2,
				ActionEvent.CTRL_MASK));*/
		subMenuItem.addActionListener(this);
		Insert.add(subMenuItem);
		subMenuItem = new JMenuItem("Class");
		Insert.add(subMenuItem);
		subMenuItem.addActionListener(this);
		subMenuItem = new JMenuItem("Relationship");
		Insert.add(subMenuItem);
		subMenuItem.addActionListener(this);
		
		editMenu.add(Insert);

	}

	
	/**
	 * Creates the text items including places to enter text and labels.
	 * Labels cannot be changed by the user.
	 * Text can be changed by the user unless it's not editable.
	 * @param widgetPanel is the JPanel that will hold the text items.
	 */
	private void createTextItems(JPanel widgetPanel) {
		
		
		
		
/*		widgetPanel.add(Box.createRigidArea(new Dimension(0,5)));
		
		JPanel panel = new JPanel();
		panel.setAlignmentX(CENTER_ALIGNMENT);
		panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
		widgetPanel.add(panel);
		
		JLabel inputLabel = new JLabel();
		panel.add(inputLabel);
		inputLabel.setText("Enter a word to find:");
		inputLabel.setAlignmentX(RIGHT_ALIGNMENT);
		
		inputField = new JTextField();
		panel.add(inputField);
		inputField.setText("");
		inputField.setEditable(true);
		inputField.setMaximumSize(new Dimension(MaxDrawingWidth,30));
		inputField.addActionListener(this);
		
		widgetPanel.add(Box.createRigidArea(new Dimension(0,5)));

		theOutputMessage = new JTextArea();
		JScrollPane scrollPane = new JScrollPane(theOutputMessage);
		widgetPanel.add(scrollPane);
		theOutputMessage.setEditable(false);
		theOutputMessage.setText("Open a Puzzle to Start");
		scrollPane.setMinimumSize(new Dimension(MinDrawingWidth,30));
		scrollPane.setPreferredSize(new Dimension(MinDrawingWidth,100));*/
	}
	
	/**
	 * Creates the button to look up a word.
	 * @param widgetPanel is the JPanel that will hold the button.
	 */
	private void createButton(JPanel widgetPanel) {
	/*	JButton findButton = new JButton(findButtonText);
		findButton.addActionListener(this);
		widgetPanel.add(findButton);
		findButton.setAlignmentX(CENTER_ALIGNMENT);*/
	}
	
	/**
	 * Prints the message in the output field.
	 * @param theMessage message to be printed
	 */
	public void printMessage(String theMessage) {
		theOutputMessage.setText(theMessage);
	}
	
	/**
	 * Returns the word currently in the input field.
	 * @return current value of the input field
	 */
	public String getWord() {
		return inputField.getText();
	}
	
	/**
	 * Handles the mouse entered event by printing a message.
	 * @param me the mouse event containing location and modifier keys
	 */
	public void mouseEntered(MouseEvent e) {
		printMessage("Mouse entered");
	}

	/**
	 * Handles the mouse exited event by printing a message.
	 * @param me the mouse event containing location and modifier keys
	 */
	 public void mouseExited(MouseEvent e) {
		 printMessage("Mouse exited");
	 }

	/**
	 * Handles the mouse click event by printing the number of clicks.
	 * @param me the mouse event containing location and modifier keys
	 */
	public void mouseClicked(MouseEvent me) {
		printMessage("Mouse clicked (# of clicks: " + me.getClickCount() + ")");	
	}
	
	/**
	 * Handles the mouse down event by printing a message..
	 * @param me the mouse event containing location and modifier keys
	 */
	public void mousePressed(MouseEvent me) {
		printMessage("MouseDown")	;
	}
	
	/**
	 * Handles the mouse up event by printing a message.
     * @param me the mouse event containing location and modifier keys
     */
	public void mouseReleased(MouseEvent me) {
		printMessage("MouseUp");	
	}
	
	/**
	 * Perform actions depending which widget was selected.
	 * Determines which sort of widget was selected and bases action on its name.
	 * Currently has actions for the find word button and the open puzzle menu.
	 * @param se the selection event including the source of the event
	 */
	public void actionPerformed(ActionEvent se) {
		if (se.getSource() == inputField) {
			findWord();
		} else {
			String command = se.getActionCommand();
			if (command == findButtonText) {
				findWord();
			} else if (command == openMenuText) {
				controller.openPuzzleFile();
			} else if (command == saveMenuText) {
				printMessage("That was a save puzzle request");
			} else {
				printMessage("Unknown action: " + command);
			}
		}
	}
	
	/**
	 * Look up the current word in the puzzle and print the result.
	 */
	private void findWord( ) {
		String theWord = getWord();
		if (theWord == null || theWord.length() <= 0) {
			printMessage("No word to find");
			return;
		}
		String theAnswer = puzzle().locationInPuzzle(theWord);
		if (theAnswer.length( ) <= 0) {
			printMessage(theWord + " not found");
		} else {
			printMessage(theAnswer);		
		}
		inputField.selectAll(); // prepares the inputField to replace with next keystrokes
		inputField.requestFocusInWindow(); // makes the input field receive keystrokes
	}
	
	/**
	 * Opens a file dialog using the provided message and 
	 * obtains the full name of a file.
	 * @param message the prompt in the file dialog box
	 * @return full path name of the file name
	 */
	public String obtainFileName(String message) {
		String theFileName = null;
		final JFileChooser fc = new JFileChooser();
		int returnVal = fc.showOpenDialog(this);
		if (returnVal == JFileChooser.APPROVE_OPTION) {
	           File file = fc.getSelectedFile();
	           try {
	        	   theFileName = file.getCanonicalPath();
	           } catch (Exception e) {
	        	   printMessage("Unable to determine file path.");
	        	   theFileName = null;
	           }
		}
  		return (theFileName);
	}
	
	
}
